package com.proxy.register;

import com.proxy.annotation.ProxyScan;
import com.proxy.configure.ProxyScannerConfiguration;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author Better Feng
 * @date 2021/8/27 11:26
 */
public class ProxyScannerRegister implements BeanFactoryAware, ImportBeanDefinitionRegistrar {

    private BeanFactory beanFactory;

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        Map<String, Object> annotationAttributes = importingClassMetadata.getAnnotationAttributes(ProxyScan.class.getName());
        if (annotationAttributes != null) {
            AnnotationAttributes attributes = AnnotationAttributes.fromMap(annotationAttributes);
            List<String> basePackages = new ArrayList<>();
            for (String pkg : attributes.getStringArray("value")) {
                if (StringUtils.hasText(pkg)) {
                    basePackages.add(pkg);
                }
            }
            for (String pkg : attributes.getStringArray("basePackages")) {
                if (StringUtils.hasText(pkg)) {
                    basePackages.add(pkg);
                }
            }
            for (Class<?> clazz : attributes.getClassArray("basePackageClasses")) {
                basePackages.add(ClassUtils.getPackageName(clazz));
            }
            BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(ProxyScannerConfiguration.class);
            builder.addPropertyValue("basePackage", StringUtils.collectionToCommaDelimitedString(basePackages));
            String beanName = generateBaseBeanName(importingClassMetadata, 0);
            registry.registerBeanDefinition(beanName, builder.getBeanDefinition());
        }
    }

    private static String generateBaseBeanName(AnnotationMetadata importingClassMetadata, int index) {
        return importingClassMetadata.getClassName() + "#" + ProxyScannerConfiguration.class.getSimpleName() + "#" + index;
    }
}
